/*
 * Copyright 2007 National Bioinformatics Network
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dgbgui.modeldocument.uimodels;

import java.util.Set;

import javax.swing.DefaultComboBoxModel;

import dgbgui.modeldocument.ModelDocument;
import dgbgui.modeldocument.Query;
import dgbgui.modeldocument.QueryResult;
import dgbgui.modeldocument.ResultStore;
import dgbgui.modeldocument.definition.RelationTypesDefinition;
import dgbgui.modeldocument.definition.ResultsDefinition;
import dgbgui.modeldocument.primitives.ConceptronType;
import dgbgui.modeldocument.primitives.RelationType;

@SuppressWarnings("serial")
public class RelationTypesComboBoxModel extends DefaultComboBoxModel {
    
    public static enum Type {
        WITH_ALL_QUERIES,
        WITHOUT_ALL_QUERIES
    }
    
    public RelationTypesComboBoxModel(Type modelType) {
        Set<ConceptronType> relationTypes = ModelDocument.getInstance().getConceptronTypes(RelationType.class);
        
        // Add *all types* 
        QueryResult allRelationTypes = new QueryResult();
        for ( ConceptronType type : relationTypes) {
            allRelationTypes.addPrimitive(type);
        }
        Query allRelationTypesQuery = new Query(new RelationTypesDefinition());
        ResultStore.getInstance().addResult(allRelationTypesQuery.getDefinition().getdgbQLString(),allRelationTypes);
        
        addElement(new CustomQueryComboItem(allRelationTypesQuery,"*All relation types*"));

        // Individual relation types
        
        for ( ConceptronType type : relationTypes) {
            // Create a query result query for each relation type
            QueryResult result = new QueryResult();
            result.addPrimitive(type);
            Query newQuery = new Query(new ResultsDefinition(result));
            ResultStore.getInstance().addResult(newQuery.getDefinition().getdgbQLString(),result);
            addElement(new CustomQueryComboItem(newQuery,type.m_name));
            
        }

        if ( modelType == Type.WITH_ALL_QUERIES ) { 
            // Add all the current queries
            QueryComboModel.addAllQueries(this);
        }
    }

    /**
     * @param query The selected query
     */
    public RelationTypesComboBoxModel(Query query,Type modelType) {
        this(modelType);
        
        // Special case 1. The query is the "All relation types"
        // custom query. Fond it in the list and set it
        boolean found = false;
        if ( query.getDefinition() instanceof RelationTypesDefinition ) {
            for ( int k = 0; k < getSize(); ++k ) {
                assert ( getElementAt(k) instanceof QueryComboItem );
                QueryComboItem item = (QueryComboItem)getElementAt(k);
                if ( item.getQuery().getDefinition() instanceof RelationTypesDefinition ) {
                    setSelectedItem(getElementAt(k));
                    found = true;
                    break;
                }
            }
        }
        
        // Now this is a bit tricky. First we check if the given query
        // is in the list. If yes, set it as selected
        if  (!found) {
            for ( int k = 0; k < getSize(); ++k ) {
                assert ( getElementAt(k) instanceof QueryComboItem );
                QueryComboItem item = (QueryComboItem)getElementAt(k);
                if ( item.getQuery() == query ) {
                    setSelectedItem(getElementAt(k));
                    found = true;
                    break;
                }
            }
        }
        
        // Third step - it's possible that the query is a 
        // result type query created for a certain result type
        if (!found && ( query.getDefinition() instanceof ResultsDefinition )) {
            QueryResult result1 = ((ResultsDefinition)query.getDefinition()).getResult();
            if ( result1.getPrimitives().size() == 1 ) {

                // Try and match within in the model
                for ( int k = 0; k < getSize(); ++k ) {
                    assert ( getElementAt(k) instanceof QueryComboItem );
                    QueryComboItem item = (QueryComboItem)getElementAt(k);

                    if (  item.getQuery().getDefinition() instanceof ResultsDefinition ) { 
                        QueryResult result2 = ((ResultsDefinition)item.getQuery().getDefinition()).getResult();
                        if ( result2.getPrimitives().size() == 1 ) {
                            if ( result1.getPrimitives().iterator().next() == result2.getPrimitives().iterator().next() ) {
                                setSelectedItem(getElementAt(k));
                                found = true;
                                break;
                            }
                        }
                    }
                }
            }
        }
        
        // If we failed, add the given query and
        // set it as selected
        if ( !found) {
            QueryComboItem newItem = new QueryComboItem(query);
            addElement(newItem);
            setSelectedItem(newItem);
        }
        
    }
    
    /**
     * Remove a query from the model
     * @param queryToEdit
     */
    public void removeQuery(Query query) {
        for ( int k = 0; k < getSize(); ++k ) {
            if ( ((QueryComboItem)getElementAt(k)).getQuery() ==  query ) {
                removeElementAt(k);
                break;
            }
        }
    }
    
    /**
     * @return the currently selected query
     */
    public Query getSelected() {
        return ((QueryComboItem)getSelectedItem()).getQuery();
    }
    


}
